home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 2 code / Secret Life of Mem. Mgr. / UDialogs.p < prev    next >
Encoding:
Text File  |  1990-05-29  |  31.2 KB  |  950 lines  |  [TEXT/MPS ]

  1. unit UDialogs;
  2. (* Written by Richard Clark (AppleLink, Delphi, GEnie, MCI, MouseHole: RDCLARK *)
  3. (*                                   Internet: rdclark@apple.com or rdclark@applelink.apple.com) *)
  4. (* Copyright (c) 1989 by Apple Computer, Inc. All Rights Reserved                       *)
  5. {$S UDialogs}
  6.  
  7. interface
  8.  
  9.     uses
  10.         Types, Memory, QuickDraw, Menus, Dialogs, Packages, Errors, OSUtils, ToolUtils,
  11.         UGlobals, UHeapHandler;
  12.  
  13.     const
  14.      (* Item numbers in the dialog box *)
  15.         dmOldHeap = 1;           (* The "Old Heap" display in the Memory dialog *)
  16.         dmNewHeap = 2;         (* The "New Heap" display in the Memory dialog *)
  17.         diNewHandle = 3;          (* The "NewHandle" button *)
  18.         diHLock = 4;                (* The "HLock" button *)
  19.         diHUnlock = 5;           (* The "HUnlock" button *)
  20.         diMoveHHi = 6;            (* The "MoveHHi" button *)
  21.         diDisposeHand = 7;      (* The "DisposHandle" button *)
  22.         diNewPtr = 8;            (* The "NewPtr" button *)
  23.         diDisposPtr = 9;           (* The "DisposPtr" button *)
  24.         diHandSize = 10;          (* The "New Handle Size" edit text item *)
  25.         diPtrSize = 11;          (* The "New Pointer Size" edit text item *)
  26.      (* Item numbers for the extended dialog *)
  27.      (* Item 17 is the "Memory Size" static text label *)
  28.         diMemSizeItem = 18;   (* The static text item representing th available memory *)
  29.      (* Item 19 is the "Largest Free" static text label *)
  30.         diContigItem = 20;        (* The static text item representing the largest contiguous block after a purge *)
  31.      (* Item 21 is the "Result" static text item *)
  32.         diResultItem = 22;      (* The result (code or number) of the last operation *)
  33.         diHPurge = 23;            (* The "HPurge" button (advanced dialog) *)
  34.         diHNoPurge = 24;            (* The "HNoPurge" button (advanced dialog) *)
  35.         diMaxMem = 25;            (* The "MaxMem" button (advanced dialog) *)
  36.         diCompactMem = 26;      (* The "CompactMem" button (advanced dialog) *)
  37.         diPurgeMem = 27;      (* The "PurgeMem" button (advanced dialog) *)
  38.         diCMSize = 28;          (* The "CompactMem" paramater edit text item *)
  39.         diPMSize = 29;          (* The "PurgeMem" paramater edit text item *)
  40.  
  41.         lastDialogItem = 29;      (* How many items are in my dialog *)
  42.  
  43.     procedure InitMyDialogs;
  44.  
  45.     procedure OpenMemoryDialog;
  46.     procedure InitMemoryDialog;
  47.     procedure InvalItem (whichItem: integer);
  48.     procedure CloseMemoryDialog;
  49.  
  50.     function HandleDialogEvents (theEvent: EventRecord): Boolean;
  51.  
  52. implementation
  53.  
  54. (* Private procedures *)
  55.  
  56.     procedure DrawItem (whichWindow: WindowPtr; itemNum: integer);
  57.    (* Draw the specified "heap" user items *)
  58.         var
  59.             itemType: integer;
  60.             itemHand: Handle;
  61.             itemRect: Rect;
  62.  
  63.     begin
  64.         SetPort(whichWindow);
  65.     (* Get the boundaries of the given display *)
  66.         GetDItem(DialogPtr(whichWindow), itemNum, itemType, itemHand, itemRect);
  67.  
  68.         case itemNum of
  69.             dmOldHeap: 
  70.                 DrawHeap(OldHeap, kDontShowSelection);
  71.  
  72.             dmNewHeap: 
  73.                 DrawHeap(CurrHeap, kDoShowSelection);
  74.         end;
  75.     end; (* DrawHeap *)
  76.  
  77.     procedure EnableButton (whichItem: integer; enabled: Boolean);
  78.         var
  79.             itemType: integer;
  80.             itemHand: Handle;
  81.             itemRect: Rect;
  82.  
  83.     begin
  84.      (* Mark this item as having been changed *)
  85.         GetDItem(memoryDialog, whichItem, itemType, itemHand, itemRect);
  86.         if enabled then
  87.             HiliteControl(ControlHandle(itemHand), 0)
  88.         else
  89.             HiliteControl(ControlHandle(itemHand), 255);
  90.     end; (* EnableButton *)
  91.  
  92.     procedure BuildNumericString (theNumber: LONGINT; var theString: Str255);
  93.         var
  94.             otherNumString, deltaString: Str255;
  95.             delta: LONGINT;
  96.  
  97.     begin
  98.         NumToString(theNumber, theString);
  99.         Insert(' bytes (', theString, length(theString) + 1);
  100.         NumToString((theNumber + 512) div 1024, otherNumString);
  101.         Insert('K', otherNumString, length(otherNumString) + 1);
  102.         if (theNumber mod 1024) > 512 then
  103.             delta := (theNumber mod 1024) - 1024
  104.         else
  105.             delta := theNumber mod 1024;
  106.         if delta <> 0 then
  107.             begin
  108.                 NumToString(delta, deltaString);
  109.                 Insert(deltaString, otherNumString, length(otherNumString) + 1);
  110.             end;
  111.         Insert(')', otherNumString, length(otherNumString) + 1);
  112.         Insert(otherNumString, theString, length(theString) + 1);
  113.     end; (* BuildNumericString*)
  114.  
  115.  
  116.     procedure ShowNumResult (theDialog: DialogPtr; result: LONGINT);
  117.         var
  118.             resultString: Str255;
  119.             itemType: INTEGER;
  120.             itemHand: handle;
  121.             itemRect: Rect;
  122.  
  123.     begin
  124.         BuildNumericString(result, resultString);
  125.         GetDItem(theDialog, diResultItem, itemType, itemHand, itemRect);
  126.         SetIText(itemHand, resultString);
  127.     end; (* ShowNumResult *)
  128.  
  129.  
  130.     procedure ShowMemError (theDialog: DialogPtr; result: INTEGER);
  131.         var
  132.             errorString: Str255;
  133.             itemType: INTEGER;
  134.             itemHand: Handle;
  135.             itemRect: Rect;
  136.  
  137.     begin
  138.         GetDItem(theDialog, diResultItem, itemType, itemHand, itemRect);
  139.         case result of
  140.             noErr: 
  141.                 errorString := 'noErr';
  142.  
  143.             memFullErr: 
  144.                 errorString := 'memFullErr';
  145.  
  146.             memPurErr: 
  147.                 errorString := 'memPurErr';
  148.  
  149.             memWZErr: 
  150.                 errorString := 'memWZErr';
  151.             otherwise
  152.                 NumToString(result, errorString);
  153.         end;
  154.         SetIText(itemHand, errorString);
  155.     end; (* ShowMemError *)
  156.  
  157.  
  158.     procedure ShowFreeMem (theDialog: DialogPtr);
  159.         var
  160.             oldValue, newValue: Str255;
  161.             memAvail, memContig: LONGINT;
  162.             itemType: INTEGER;
  163.             itemHand: Handle;
  164.             itemRect: Rect;
  165.  
  166.     begin
  167.         SetZone(MyDemoZone);
  168.         if System.EnhancedROMs then
  169.             PurgeSpace(memAvail, memContig)
  170.         else
  171.             memAvail := FreeMem; (* div 1024 *)
  172.         SetZone(MyAppZone);
  173.  
  174.         BuildNumericString(memAvail, newValue);
  175.         GetDItem(theDialog, diMemSizeItem, itemType, itemHand, itemRect);
  176.         GetIText(itemHand, oldValue);
  177.         if (oldValue <> newValue) then
  178.             SetIText(itemHand, newValue);
  179.  
  180.         if System.EnhancedROMs then
  181.             BuildNumericString(memContig, newValue)
  182.         else
  183.             newValue := 'Not available';
  184.         GetDItem(theDialog, diContigItem, itemType, itemHand, itemRect);
  185.         GetIText(itemHand, oldValue);
  186.         if (oldValue <> newValue) then
  187.             SetIText(itemHand, newValue);
  188.  
  189.     end; (* ShowFreeMem *)
  190.  
  191.  
  192.  
  193.     procedure InitMemoryDialog;
  194.         var
  195.             itemType: integer;
  196.             itemHand: Handle;
  197.             itemRect: Rect;
  198.  
  199.     begin
  200.      (* Install the 2 heap displays as user items *)
  201.         GetDItem(memoryDialog, dmOldHeap, itemType, itemHand, itemRect);
  202.         SetDItem(memoryDialog, dmOldHeap, itemType, Handle(@DrawItem), itemRect);
  203.         OldHeap.heapRect := itemRect;
  204.         with itemRect do
  205.             BytesPerPixel := (MyHeapSize * 1024) div (bottom - top);
  206.         GetDItem(memoryDialog, dmNewHeap, itemType, itemHand, itemRect);
  207.         SetDItem(memoryDialog, dmNewHeap, itemType, Handle(@DrawItem), itemRect);
  208.         CurrHeap.heapRect := itemRect;
  209.  
  210.      (* Enable and disable the appropriate buttons *)
  211.         EnableButton(diNewHandle, TRUE);
  212.         EnableButton(diHLock, FALSE);
  213.         EnableButton(diMoveHHi, FALSE);
  214.         EnableButton(diHUnlock, FALSE);
  215.         if application.UseExtendedDialog then
  216.             begin
  217.                 EnableButton(diHPurge, FALSE);
  218.                 EnableButton(diHNoPurge, FALSE);
  219.             end;
  220.         EnableButton(diDisposeHand, FALSE);
  221.         EnableButton(diNewPtr, TRUE);
  222.         EnableButton(diDisposPtr, FALSE);
  223.  
  224.         SetWRefCon(memoryDialog, MemDialogRefCon);
  225.         ShowMemError(memoryDialog, 0);
  226.         ShowFreeMem(memoryDialog);
  227.     end; (* InitMemoryDialog *)
  228.  
  229. (* Public Procedures *)
  230.  
  231.     procedure SelectBlock (whichBlock: INTEGER; var whichHeap: HeapInfo; heapRect: Rect);
  232.    (* Mark te specific block as "selected" (i.e. highlighted). 0 de-selects all blocks *)
  233.         var
  234.             oldSelection: INTEGER;
  235.             isLocked, isPurgeable: Boolean;
  236.  
  237.     begin
  238.         oldSelection := whichHeap.selectedBlock;
  239.         whichHeap.selectedBlock := whichBlock;
  240.         if (oldSelection <> 0) then
  241.             DrawBlock(oldSelection, whichHeap, kDoShowSelection);
  242.         if (whichBlock <> 0) then
  243.             begin
  244.                 case CurrHeap.blocks[whichBlock].blkType of
  245.                     blkHandle: 
  246.                         begin
  247.                             isLocked := CurrHeap.blocks[whichBlock].blkLocked;
  248.                             isPurgeable := CurrHeap.blocks[whichBlock].blkPurgeable;
  249.                             EnableButton(diHLock, not isLocked);
  250.                             EnableButton(diHUnlock, isLocked);
  251.                             EnableButton(diMoveHHi, not isLocked);
  252.                             if application.UseExtendedDialog then
  253.                                 begin
  254.                                     EnableButton(diHPurge, not isPurgeable);
  255.                                     EnableButton(diHNoPurge, isPurgeable);
  256.                                 end;
  257.                             EnableButton(diDisposeHand, TRUE);
  258.                             EnableButton(diDisposPtr, FALSE);
  259.                         end;
  260.  
  261.                     blkPointer: 
  262.                         begin
  263.                             EnableButton(diHLock, FALSE);
  264.                             EnableButton(diHUnlock, FALSE);
  265.                             EnableButton(diMoveHHi, FALSE);
  266.                             EnableButton(diDisposeHand, FALSE);
  267.                             EnableButton(diDisposPtr, TRUE);
  268.                             if application.UseExtendedDialog then
  269.                                 begin
  270.                                     EnableButton(diHPurge, FALSE);
  271.                                     EnableButton(diHNoPurge, FALSE);
  272.                                 end;
  273.                         end;
  274.                 end; (* case *)
  275.                 DrawBlock(whichBlock, whichHeap, kDoShowSelection);
  276.             end
  277.         else
  278.             begin
  279.                 EnableButton(diHLock, FALSE);
  280.                 EnableButton(diHUnlock, FALSE);
  281.                 EnableButton(diMoveHHi, FALSE);
  282.                 EnableButton(diDisposeHand, FALSE);
  283.                 EnableButton(diDisposPtr, FALSE);
  284.                 if application.UseExtendedDialog then
  285.                     begin
  286.                         EnableButton(diHPurge, FALSE);
  287.                         EnableButton(diHNoPurge, FALSE);
  288.                     end;
  289.             end;
  290.     end; (* SelectBlock *)
  291.  
  292.  
  293.     procedure InitMyDialogs;
  294.    (* Initialize dialog-related global variables *)
  295.     begin
  296.         memoryDialog := nil;
  297.     end; (* InitMyDialogs *)
  298.  
  299.  
  300.     procedure OpenMemoryDialog;
  301.         var
  302.             itemType: INTEGER;
  303.             itemHand: Handle;
  304.             itemRect: Rect;
  305.  
  306.     begin
  307.         if (memoryDialog = nil) then
  308.             begin
  309.                 if application.UseExtendedDialog then
  310.                     memoryDialog := GetNewDialog(dExtendedMemory, nil, WindowPtr(-1))
  311.                 else
  312.                     memoryDialog := GetNewDialog(dShortMemory, nil, WindowPtr(-1));
  313.                 if memoryDialog <> nil then
  314.                     begin
  315.                         InitMemoryDialog;
  316.                         DisableItem(FileMenu, ifOpen);
  317.                         GetDItem(memoryDialog, dmNewHeap, itemType, itemHand, itemRect);
  318.                         SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  319.                         ShowWindow(memoryDialog);
  320.                         (* Changes added for version 1.3.4 *)
  321.                         EnableItem(WindowMenu, imSimpleDialog);
  322.                         EnableItem(WindowMenu, imComplexDialog);
  323.                         IF CurrHeap.BlocksUsed > 0 THEN
  324.                             EnableItem(SpecialMenu, isEraseHeap)
  325.                         ELSE
  326.                             DisableItem(SpecialMenu, isEraseHeap);
  327.                         DrawMenuBar;
  328.                     end;
  329.             end;
  330.     end; (* OpenMemoryDialog *)
  331.  
  332.  
  333.     procedure InvalItem;
  334.    (* Invalidate the specified dialog item, forcing it to be redrawn *)
  335.         var
  336.             itemType: integer;
  337.             itemHand: Handle;
  338.             itemRect: Rect;
  339.             oldPort: GrafPtr;
  340.  
  341.     begin
  342.         GetDItem(memoryDialog, whichItem, itemType, itemHand, itemRect);
  343.         GetPort(oldPort);
  344.         SetPort(memoryDialog);
  345.         InvalRect(itemRect);
  346.         SetPort(oldPort);
  347.     end; (* InvalItem *)
  348.  
  349.  
  350.     procedure CloseMemoryDialog;
  351.     begin
  352.         if memoryDialog <> nil then
  353.             begin
  354.                 DisposDialog(memoryDialog);
  355.                 memoryDialog := nil;
  356.                 EnableItem(FileMenu, ifOpen);
  357.                 (* Changes added for version 1.3.4 *)
  358.                 DisableItem(WindowMenu, imSimpleDialog);
  359.                 DisableItem(WindowMenu, imComplexDialog);
  360.                 DisableItem(SpecialMenu, isEraseHeap);
  361.                 DrawMenuBar;
  362.             END;
  363.     end; (* CloseMemoryDialog *)
  364.  
  365.  
  366.     function GetItemNumber (theDialog: DialogPtr; theItem: INTEGER): LongInt;
  367.         var
  368.             n: LONGINT;
  369.             itemString: Str255;
  370.             itemType: INTEGER;
  371.             item: Handle;
  372.             bounds: Rect;
  373.             i: Integer;
  374.  
  375.     begin
  376.         GetDItem(theDialog, theItem, itemType, item, bounds);
  377.         GetIText(item, itemString);
  378.         for i := 1 to LENGTH(itemString) do
  379.             begin
  380.                 if (itemString[i] < '0') or (itemString[i] > '9') then
  381.                     begin
  382.                         itemString[i] := '0';                    (* We could do something better here… *)
  383.                     end;
  384.             end;
  385.         StringToNum(itemString, n);
  386.         GetItemNumber := n;
  387.     end; {of GetItemNumber}
  388.  
  389.  
  390.     procedure DoMouseInHeap (theEvent: EventRecord; theDialog: DialogPtr; theItem: INTEGER);
  391.    (* Handle mouse downs in one of the "heap" user items *)
  392.         var
  393.             itemType: INTEGER;
  394.             itemhand: Handle;
  395.             itemRect: Rect;
  396.         (* The following are used by the block search mechanism *)
  397.             byteOffset: LONGINT;
  398.             blkCount: INTEGER;
  399.             found: Boolean;
  400.  
  401.     begin
  402.      (* This is called if the user clicks in the Current heap display area *)
  403.      (* It should set the number of the currently selected block *)
  404.         GlobalToLocal(theEvent.where);
  405.         GetDItem(theDialog, theItem, itemType, itemHand, itemRect);
  406.         if PtInRect(theEvent.where, itemRect) then
  407.             begin
  408.                 found := FALSE;
  409.                 byteOffset := BytesPerPixel * (itemRect.bottom - theEvent.where.v) + ORD(MyDemoZone) + HeapBias;
  410.                 with CurrHeap do
  411.                     for blkCount := 1 to MyArraySize do
  412.                         with blocks[blkCount] do
  413.                             if (blkType <> blkFree) then
  414.                                 if (byteOffset >= blkStart) and (byteOffset <= (blkStart + blkSize)) then
  415.                                     begin
  416.                                         SelectBlock(blkCount, CurrHeap, itemRect);
  417.                                         found := TRUE;
  418.                                     end;
  419.                 if not found then
  420.                     SelectBlock(0, CurrHeap, itemRect);
  421.             end;
  422.     end; (* DoMouseInHeap *)
  423.  
  424.  
  425.     function CheckAllocRequest (requested: integer; theHeap: HeapInfo; var freeBlock: integer): boolean;
  426.    (* Verify that the number lies between 1 and the heap size (16). If so, retrn TRUE. If not, put *)
  427.    (* up an alert notifying the user of the error. This also returns the number of the first free block *)
  428.    (* in the current heap array.                                                                                *)
  429.         var
  430.             blockCount: integer;
  431.             alertItem: integer;
  432.             nBlocks: Str255;
  433.  
  434.     begin
  435.         blockCount := 1;
  436.         freeBlock := 0;
  437.       (* Look for a free block in the Current Heap array *)
  438.         while (blockCount <= MyArraySize) and (freeBlock = 0) do
  439.             if theHeap.blocks[blockCount].blkType = blkFree then
  440.                 freeBlock := blockCount
  441.             else
  442.                 blockCount := blockCount + 1;
  443.  
  444.       (* Call NumToStr and SetIText to insert MyHeapSize into the dialog's text *)
  445.         NumToString(MyHeapSize, nBlocks);
  446.         ParamText(nBlocks, '', '', '');
  447.         if (freeBlock = 0) then
  448.             begin
  449.                 alertItem := StopAlert(aNoMoreBlocks, nil);
  450.                 CheckAllocRequest := FALSE;
  451.             end
  452.         else if (requested < 1) or (requested > MyHeapSize) then
  453.             begin
  454.                 alertItem := StopAlert(aBadNumber, nil);
  455.                 CheckAllocRequest := FALSE;
  456.             end
  457.         else
  458.             CheckAllocRequest := TRUE;
  459.     end; (* CheckAllocRequest *)
  460.  
  461.  
  462.     function CheckGeneralRequest (requested: INTEGER): Boolean;
  463.    (* Make sure that the number is between 0 and the block size (16). Put up an alert if not *)
  464.         var
  465.             alertItem: INTEGER;
  466.  
  467.     begin
  468.         if (requested < 1) or (requested > MyHeapSize) then
  469.             begin
  470.                 alertItem := StopAlert(aBadNumber, nil);
  471.                 CheckGeneralRequest := FALSE;
  472.             end
  473.         else
  474.             CheckGeneralRequest := TRUE;
  475.     end; (* CheckGeneralRequest *)
  476.  
  477.  
  478.     function CheckResult (result: Ptr): Boolean;
  479.    (* Alert the user if the supplied pointer (or handle) is nil *)
  480.         var
  481.             oldZone: THz;
  482.             alertItem: integer;
  483.  
  484.     begin
  485.         if (result = nil) then
  486.             begin
  487.                 oldZone := GetZone;
  488.                 SetZone(MyAppZone);
  489.                 alertItem := NoteAlert(aNoDemoMemory, nil);
  490.                 SetZone(oldZone);
  491.                 CheckResult := FALSE;
  492.             end
  493.         else
  494.             CheckResult := TRUE;
  495.     end; (* CheckResult *)
  496.  
  497.     procedure HandleDialogClicks (theEvent: EventRecord; theDialog: DialogPtr; itemHit: INTEGER);
  498.    (* Process clicks in the Memory dialog*)
  499.         var
  500.             scratchHand: Handle;
  501.             scratchPtr: Ptr;
  502.             freeBlock: integer;
  503.             numBytes: LongInt;
  504.             alertItem: integer;
  505.             itemType: INTEGER;
  506.             itemHand: Handle;
  507.             itemRect: Rect;
  508.             grow, result, remainder: LONGINT;
  509.  
  510.     begin
  511.         SetPort(theDialog);
  512.         if (itemHit = dmOldHeap) then
  513.             alertItem := NoteAlert(aNoOldHeap, nil)
  514.         else if (itemHit = dmNewHeap) then
  515.             DoMouseInHeap(theEvent, theDialog, itemHit)
  516.         else if (itemHit >= diNewHandle) and (itemHit <= lastDialogItem) then
  517.             case itemHit of
  518.  
  519.                 diNewHandle:                                 {The "NewHandle" button was hit }
  520.                     begin
  521.                         numBytes := GetItemNumber(theDialog, diHandSize);
  522.                 (* Look for a valid size and a free block *)
  523.                         if (CheckAllocRequest(numBytes, CurrHeap, freeBlock)) then
  524.                             with CurrHeap do
  525.                                 begin
  526.                                     GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  527.                                     SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  528.                                     CopyHeapInfo(CurrHeap, OldHeap);                                (* Move the heap's status to the "old heap" array *)
  529.                                     UpdateHeapInfo(OldHeap, kClearDirtyFlags);                        (* Calculate the physical locations of these blocks in the display *)
  530.                                     UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  531.                                     SetZone(MyDemoZone);                                            (* Switch to the mini-heap, and do the operation *)
  532.                                     scratchHand := NewHandle(numBytes * 1024 - BlockHeaderSize);
  533.                                     result := MemError;                                                (* get a result code *)
  534.                                     SetZone(MyAppZone);
  535.                                     if (CheckResult(Ptr(scratchHand))) then                        (* See if the allocation happened fine. If not,warn the user *)
  536.                                         begin
  537.                                             numBlocks := numBlocks + 1;                                    (* Update the "currnet blocks" count *)
  538.                                             blocksUsed := blocksUsed + 1;                                (* Update the block serial number counter *)
  539.                                             with blocks[freeBlock] do
  540.                                                 begin                                                            (* Initialize this entry in the array *)
  541.                                                     blkStart := ORD(scratchHand^);
  542.                                                     blkSource := Ptr(scratchHand);
  543.                                                     blkType := blkHandle;
  544.                                                     blkSize := numBytes * 1024;
  545.                                                     blkSequence := numBlocks;
  546.                                                     HUnlock(scratchHand);
  547.                                                     HNoPurge(scratchHand);
  548.                                                     blkLocked := FALSE;
  549.                                                     blkPurgeable := FALSE;
  550.                                                     blkDirty := TRUE;
  551.                                                 end;
  552.                                         end;
  553.                                     UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  554.                                     EnableButton(diNewHandle, TRUE); (* was "(blocksUsed < MyHeapSize) and  (CurrHeap.MaxBlocks > 0)" *)
  555.                                     EnableButton(diNewPtr, TRUE); (* was "(blocksUsed < MyHeapSize) and (CurrHeap.MaxBlocks > 0)" *)
  556.                                     InvalItem(dmNewHeap);                            (* Redraw both heap displays *)
  557.                                     InvalItem(dmOldHeap);
  558.                                     ShowMemError(theDialog, result);                (* Show the result of the last operation *)
  559.                                     ShowFreeMem(theDialog);                            (* Show how much memory is left *)
  560.                                 end;
  561.                     end;
  562.  
  563.                 diNewPtr: 
  564.                     begin
  565.                         numBytes := GetItemNumber(theDialog, diPtrSize);  { diPtrSize is the NewHdl text box}
  566.                         if (CheckAllocRequest(numBytes, CurrHeap, freeBlock)) then
  567.                             with CurrHeap do
  568.                                 begin
  569.                                     GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  570.                                     SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  571.                                     CopyHeapInfo(CurrHeap, OldHeap);
  572.                                     UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  573.                                     UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  574.                                     SetZone(MyDemoZone);
  575.                                     scratchPtr := NewPtr(numBytes * 1024 - BlockHeaderSize);
  576.                                     result := MemError;
  577.                                     SetZone(MyAppZone);
  578.                                     if (CheckResult(scratchPtr)) then
  579.                                         begin
  580.                                             numBlocks := numBlocks + 1;
  581.                                             blocksUsed := blocksUsed + 1;
  582.                                             with blocks[freeBlock] do
  583.                                                 begin
  584.                                                     blkStart := ORD(scratchPtr);
  585.                                                     blkOldStart := ORD(scratchPtr);
  586.                                                     blkSource := Ptr(scratchPtr);
  587.                                                     blkType := blkPointer;
  588.                                                     blkSize := numBytes * 1024;
  589.                                                     blkSequence := numBlocks;
  590.                                                     blkLocked := FALSE;      (* Actually, this doesn't apply to this kind of block *)
  591.                                                     blkPurgeable := FALSE;
  592.                                                     blkDirty := TRUE;
  593.                                                 end;
  594.                                         end;
  595.                                     UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  596.                                     EnableButton(diNewHandle, TRUE); (* was "(blocksUsed < MyHeapSize) and  (CurrHeap.MaxBlocks > 0)" *)
  597.                                     EnableButton(diNewPtr, TRUE); (* was "(blocksUsed < MyHeapSize) and (CurrHeap.MaxBlocks > 0)" *)
  598.                                     InvalItem(dmNewHeap);
  599.                                     InvalItem(dmOldHeap);
  600.                                     ShowMemError(theDialog, result);
  601.                                     ShowFreeMem(theDialog);
  602.                                 end;
  603.                     end;
  604.  
  605.                 diDisposeHand: {DisposHandle button}
  606.                     with CurrHeap do
  607.                         if selectedBlock <> 0 then
  608.                             begin
  609.                                 with blocks[selectedBlock] do
  610.                                     if (blkType <> blkHandle) then
  611.                                         SysBeep(5)
  612.                                     else
  613.                                         begin
  614.                                             CopyHeapInfo(CurrHeap, OldHeap);
  615.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  616.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  617.                                             blocksUsed := blocksUsed - 1;
  618.                                             blkType := blkFree;
  619.                                             SetZone(MyDemoZone);
  620.                                             DisposHandle(Handle(blkSource));
  621.                                             result := MemError;
  622.                                             SetZone(MyAppZone);
  623.                                             blkSource := nil;
  624.                                             blkStart := 0;
  625.                                             blkDirty := TRUE;
  626.                                             EnableButton(diNewHandle, TRUE);
  627.                                             EnableButton(diNewPtr, TRUE);
  628.                                         end;
  629.                                 GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  630.                                 SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  631.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  632.                                 InvalItem(dmNewHeap);
  633.                                 InvalItem(dmOldHeap);
  634.                                 ShowMemError(theDialog, result);
  635.                                 ShowFreeMem(theDialog);
  636.                             end
  637.                         else
  638.                             SysBeep(5);
  639.  
  640.                 diDisposPtr:{DisposPtr button}
  641.                     with CurrHeap do
  642.                         if selectedBlock <> 0 then
  643.                             begin
  644.                                 with blocks[selectedBlock] do
  645.                                     if (blkType <> blkPointer) then
  646.                                         SysBeep(5)
  647.                                     else
  648.                                         begin
  649.                                             CopyHeapInfo(CurrHeap, OldHeap);
  650.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  651.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  652.                                             blkType := blkFree;
  653.                                             blocksUsed := blocksUsed - 1;
  654.                                             SetZone(MyDemoZone);
  655.                                             DisposPtr(blkSource);
  656.                                             result := MemError;
  657.                                             SetZone(MyAppZone);
  658.                                             blkSource := nil;
  659.                                             blkStart := 0;
  660.                            (* We won't change the size or start figures just yet *)
  661.                                             blkDirty := TRUE;
  662.                                             EnableButton(diNewHandle, TRUE);
  663.                                             EnableButton(diNewPtr, TRUE);
  664.                                         end;
  665.                                 GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  666.                                 SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  667.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  668.                                 InvalItem(dmNewHeap);
  669.                                 InvalItem(dmOldHeap);
  670.                                 ShowMemError(theDialog, result);
  671.                                 ShowFreeMem(theDialog);
  672.                             end
  673.                         else
  674.                             SysBeep(5);
  675.  
  676.                 diHLock: 
  677.                     with CurrHeap do
  678.                         if selectedBlock <> 0 then
  679.                             begin
  680.                                 with blocks[selectedBlock] do
  681.                                     if (blkType <> blkHandle) then
  682.                                         SysBeep(5)
  683.                                     else
  684.                                         begin
  685.                                             CopyHeapInfo(CurrHeap, OldHeap);
  686.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  687.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  688.                                             SetZone(MyDemoZone);
  689.                                             HLock(Handle(blkSource));
  690.                                             result := MemError;
  691.                                             SetZone(MyAppZone);
  692.                                             blkLocked := TRUE;
  693.                                             blkDirty := TRUE;
  694.                                             EnableButton(diHLock, FALSE);
  695.                                             EnableButton(diHUnlock, TRUE);
  696.                                             EnableButton(diMoveHHi, FALSE);
  697.                                         end;
  698.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  699.                                 InvalItem(dmNewHeap);
  700.                                 InvalItem(dmOldHeap);
  701.                                 ShowMemError(theDialog, result);
  702.                                 ShowFreeMem(theDialog);
  703.                             end
  704.                         else
  705.                             SysBeep(5);
  706.  
  707.                 diHUnlock: 
  708.                     with CurrHeap do
  709.                         if selectedBlock <> 0 then
  710.                             begin
  711.                                 with blocks[selectedBlock] do
  712.                                     if (blkType <> blkHandle) then
  713.                                         SysBeep(5)
  714.                                     else
  715.                                         begin
  716.                                             CopyHeapInfo(CurrHeap, OldHeap);
  717.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  718.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  719.                                             SetZone(MyDemoZone);
  720.                                             HUnlock(Handle(blkSource));
  721.                                             result := MemError;
  722.                                             SetZone(MyAppZone);
  723.                                             blkLocked := FALSE;
  724.                                             EnableButton(diHLock, TRUE);
  725.                                             EnableButton(diHUnlock, FALSE);
  726.                                             EnableButton(diMoveHHi, TRUE);
  727.                                             blkDirty := TRUE;
  728.                                         end;
  729.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  730.                                 InvalItem(dmNewHeap);
  731.                                 InvalItem(dmOldHeap);
  732.                                 ShowMemError(theDialog, result);
  733.                                 ShowFreeMem(theDialog);
  734.                             end
  735.                         else
  736.                             SysBeep(5);
  737.  
  738.                 diMoveHHi: 
  739.                     with CurrHeap do
  740.                         if selectedBlock <> 0 then
  741.                             begin
  742.                                 with blocks[selectedBlock] do
  743.                                     if (blkType <> blkHandle) then
  744.                                         SysBeep(5)
  745.                                     else
  746.                                         begin
  747.                                             CopyHeapInfo(CurrHeap, OldHeap);
  748.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  749.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  750.                                             blkStart := ORD(blkSource^);
  751.                                             SetZone(MyDemoZone);
  752.                                             MoveHHi(Handle(blkSource));
  753.                                             result := MemError;
  754.                                             SetZone(MyAppZone);
  755.                                             blkDirty := TRUE;
  756.                                         end;
  757.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  758.                                 InvalItem(dmNewHeap);
  759.                                 InvalItem(dmOldHeap);
  760.                                 ShowMemError(theDialog, result);
  761.                                 ShowFreeMem(theDialog);
  762.                             end
  763.                         else
  764.                             SysBeep(5);
  765.  
  766.                 diHPurge: 
  767.                     with CurrHeap do
  768.                         if selectedBlock <> 0 then
  769.                             begin
  770.                                 with blocks[selectedBlock] do
  771.                                     if (blkType <> blkHandle) then
  772.                                         SysBeep(5)
  773.                                     else
  774.                                         begin
  775.                                             CopyHeapInfo(CurrHeap, OldHeap);
  776.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  777.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  778.                                             SetZone(MyDemoZone);
  779.                                             HPurge(Handle(blkSource));
  780.                                             result := MemError;
  781.                                             remainder := FreeMem;
  782.                                             SetZone(MyAppZone);
  783.                                             blkPurgeable := TRUE;
  784.                                             EnableButton(diHPurge, FALSE);
  785.                                             EnableButton(diHNoPurge, TRUE);
  786.                                             EnableButton(diNewHandle, TRUE);                                (* remainder > 0 *)
  787.                                             EnableButton(diNewPtr, TRUE);                                (* remainder > 0 *)
  788.                                             blkDirty := TRUE;
  789.                                         end;
  790.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  791.                                 InvalItem(dmNewHeap);
  792.                                 InvalItem(dmOldHeap);
  793.                                 ShowMemError(theDialog, result);
  794.                                 ShowFreeMem(theDialog);
  795.                             end
  796.                         else
  797.                             SysBeep(5);
  798.  
  799.                 diHNoPurge: 
  800.                     with CurrHeap do
  801.                         if selectedBlock <> 0 then
  802.                             begin
  803.                                 with blocks[selectedBlock] do
  804.                                     if (blkType <> blkHandle) then
  805.                                         SysBeep(5)
  806.                                     else
  807.                                         begin
  808.                                             CopyHeapInfo(CurrHeap, OldHeap);
  809.                                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  810.                                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  811.                                             SetZone(MyDemoZone);
  812.                                             HNoPurge(Handle(blkSource));
  813.                                             result := MemError;
  814.                                             SetZone(MyAppZone);
  815.                                             blkPurgeable := FALSE;
  816.                                             EnableButton(diHPurge, TRUE);
  817.                                             EnableButton(diHNoPurge, FALSE);
  818.                                             blkDirty := TRUE;
  819.                                         end;
  820.                                 UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  821.                                 InvalItem(dmNewHeap);
  822.                                 InvalItem(dmOldHeap);
  823.                                 ShowMemError(theDialog, result);
  824.                                 ShowFreeMem(theDialog);
  825.                             end
  826.                         else
  827.                             SysBeep(5);
  828.  
  829.                 diMaxMem:
  830.            (* Copy the info,  Call MaxMem,  Update the heap, Inval the heaps *)
  831.                     with CurrHeap do
  832.                         begin
  833.                             GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  834.                             SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  835.                             CopyHeapInfo(CurrHeap, OldHeap);
  836.                             UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  837.                             UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  838.                             SetZone(MyDemoZone);
  839.                             grow := 0;
  840.                             result := MaxMem(grow);
  841.                             SetZone(MyAppZone);
  842.                             UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  843.                             InvalItem(dmNewHeap);
  844.                             InvalItem(dmOldHeap);
  845.                             ShowNumResult(theDialog, result);
  846.                             ShowFreeMem(theDialog);
  847.                         end;
  848.  
  849.                 diCompactMem: 
  850.                     begin
  851.             (* Get the CM Size,  Check it,  Copy the info,  Call CompactMem,  Update the heap, Inval the heaps *)
  852.                         numBytes := GetItemNumber(theDialog, diCMSize);
  853.                         if (CheckGeneralRequest(numBytes)) then
  854.                             with CurrHeap do
  855.                                 begin
  856.                                     GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  857.                                     SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  858.                                     CopyHeapInfo(CurrHeap, OldHeap);
  859.                                     UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  860.                                     UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  861.                                     SetZone(MyDemoZone);
  862.                                     result := CompactMem(numBytes * 1024); (* - BlockHeaderSize *)
  863.                                     SetZone(MyAppZone);
  864.                                     UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  865.                                     InvalItem(dmNewHeap);
  866.                                     InvalItem(dmOldHeap);
  867.                                     ShowFreeMem(theDialog);
  868.                                     ShowNumResult(theDialog, result);
  869.                                 end;
  870.                     end;
  871.  
  872.                 diPurgeMem: 
  873.                     begin
  874.             (* Get the PM Size,  Check it,  Copy the info,  Call PurgeMem,  Update the heap, Inval the heaps *)
  875.                         numBytes := GetItemNumber(theDialog, diPMSize);
  876.                         if (CheckGeneralRequest(numBytes)) then
  877.                             with CurrHeap do
  878.                                 begin
  879.                                     GetDItem(theDialog, dmNewHeap, itemType, itemHand, itemRect);
  880.                                     SelectBlock(0, CurrHeap, itemRect);                                       (* De-select any previously chosen block *)
  881.                                     CopyHeapInfo(CurrHeap, OldHeap);
  882.                                     UpdateHeapInfo(OldHeap, kClearDirtyFlags);
  883.                                     UpdateHeapInfo(CurrHeap, kClearDirtyFlags);                           (* clean up the "dirty" flags in the current heap now *)
  884.                                     SetZone(MyDemoZone);
  885.                                     PurgeMem(numBytes * 1024 - BlockHeaderSize);
  886.                                     result := MemError;
  887.                                     SetZone(MyAppZone);
  888.                                     UpdateHeapInfo(CurrHeap, kLeaveDirtyFlags);
  889.                                     InvalItem(dmNewHeap);
  890.                                     InvalItem(dmOldHeap);
  891.                                     ShowMemError(theDialog, result);
  892.                                     ShowFreeMem(theDialog);
  893.                                 end;
  894.                     end;
  895.             end; {of case}
  896.         (* Special menu enable logic added to version 1.3.4 *)
  897.         IF CurrHeap.BlocksUsed > 0 THEN
  898.             EnableItem(SpecialMenu, isEraseHeap)
  899.         ELSE
  900.             DisableItem(SpecialMenu, isEraseHeap);
  901.         (* If the menu changed state, then re-draw the menu bar *)
  902.         IF ((CurrHeap.blocksUsed = 0) AND (oldHeap.blocksUsed > 0)) OR
  903.            ((CurrHeap.blocksUsed > 0) AND (oldHeap.blocksUsed = 0)) THEN
  904.            DrawMenuBar;
  905.     end; (* handleDialogClicks *)
  906.  
  907.  
  908.     function HandleDialogEvents;
  909.         const
  910.             bs = 8;
  911.             tab = 9;
  912.             left = 28;
  913.             right = 29;
  914.  
  915.         var
  916.             whichDialog: DialogPtr;
  917.             eventHandled: Boolean;
  918.             itemHit: INTEGER;
  919.             ch: char;
  920.  
  921.     begin
  922.         eventHandled := false;
  923.         if IsDialogEvent(theEvent) then
  924.             begin
  925.              (* Pass all dialog events to DialogSelect(), except for command-keys (for menus) *)
  926.                 if (theEvent.what = KeyDown) then
  927.                     begin
  928.                         if (BitAnd(theEvent.modifiers, cmdKey) = 0) then  (* We have a dialog key, so filter out un-wanted characters *)
  929.                             begin
  930.                                 ch := CHR(BitAnd(theEvent.message, charCodeMask));
  931.                                 if (ch in ['0'..'9', CHR(bs), CHR(tab), CHR(left), CHR(right)]) then
  932.                         (* If it's a number, <Del>, or the right and left arrows, then process it *)
  933.                                     eventHandled := DialogSelect(theEvent, whichDialog, itemHit)
  934.                                 else
  935.                                     SysBeep(5);   (* Otherwise, complain *)
  936.                             end;
  937.                     end
  938.                 else  (* Otherwise, it's not a key-down event *)
  939.                     begin
  940.                         if DialogSelect(theEvent, whichDialog, itemHit) then
  941.                             begin
  942.                                 eventHandled := true;
  943.                                 handleDialogClicks(theEvent, whichDialog, itemHit);
  944.                             end; (* case *)
  945.                     end; {of if DialogSelect}
  946.             end;
  947.         HandleDialogEvents := eventHandled;
  948.     end; (* HandleDialogEvents *)
  949.  
  950. end.